#include <iostream>
#include <string>
#include <sstream>
#include <jsoncpp/json/json.h>
#include <memory>

// 实现序列化
bool serialize(const Json::Value &val, std::string &body)
{
    std::stringstream ss;
    Json::StreamWriterBuilder swb;
    // 禁用 Unicode 转义，使中文字符直接输出
    swb.settings_["emitUTF8"] = true;
    std::unique_ptr<Json::StreamWriter> sw(swb.newStreamWriter());
    
    int ret = sw->write(val, &ss);
    if (ret != 0)
    {
        std::cerr << "json serialize failed" << std::endl;
        return false;
    }
    body = ss.str();
    return true;
}

// 实现反序列化
bool unserialize(const std::string &body, Json::Value &val)
{
    Json::CharReaderBuilder crb;
    std::string errs;
    std::unique_ptr<Json::CharReader> cr(crb.newCharReader());
    
    bool ret = cr->parse(body.c_str(), body.c_str() + body.size(), &val, &errs);
    if (!ret)
    {
        std::cerr << "json unserialize failed: " << errs << std::endl;
        return false;
    }
    return true;
}

int main()
{
    // 序列化示例
    const char *name = "小明";
    int age = 12;
    const char *sex = "男";
    float score[3] = {33, 45, 34};
    
    Json::Value student;
    student["姓名"] = name;
    student["年龄"] = age;
    student["性别"] = sex;
    
    for(int i = 0; i < 3; i++) {
        student["成绩"].append(score[i]);
    }

    Json::Value fav;
    fav["书籍"] = "西游记";
    fav["运动"] = "游泳";
    student["爱好"] = fav;
    
    std::string body;
    if(!serialize(student, body)) {
        return 1;
    }
    std::cout << "序列化结果: " << body << std::endl;

    // 反序列化示例
    Json::Value stu;
    std::string str = R"({"姓名":"夏黑","年龄":12,"成绩":[23,23],"爱好":{"书籍":"西游记","运动":"游泳"}})";
    
    if(!unserialize(str, stu)) {
        return 1;
    }

    std::cout << "\n反序列化结果:" << std::endl;
    std::cout << "姓名: " << stu["姓名"].asString() << std::endl;
    std::cout << "年龄: " << stu["年龄"].asInt() << std::endl;
    
    if(stu.isMember("成绩") && stu["成绩"].isArray()) {
        for (int i = 0; i < stu["成绩"].size(); i++)
        {
            std::cout << "成绩" << i+1 << ": " << stu["成绩"][i].asFloat() << std::endl;
        }
    }

    if(stu.isMember("爱好")) {
        std::cout << "爱好-书籍: " << stu["爱好"]["书籍"].asString() << std::endl;
        std::cout << "爱好-运动: " << stu["爱好"]["运动"].asString() << std::endl;
    }

    return 0;
}